gmfn = mfn_to_gmfn(owner, page_to_mfn(page));
ASSERT(VALID_M2P(gmfn));
- shadow_lock(owner);
shadow_remove_all_shadows(owner->vcpu[0], _mfn(gmfn));
- shadow_unlock(owner);
}
}
* 2. Shadow mode reuses this field for shadowed page tables to
* store flags info -- we don't want to conflict with that.
*/
- if ( !shadow_mode_enabled(page_get_owner(page)) ||
- ((nx & PGT_type_mask) == PGT_writable_page) )
+ if ( !(shadow_mode_enabled(page_get_owner(page)) &&
+ (page->count_info & PGC_page_table)) )
page->tlbflush_timestamp = tlbflush_current_time();
}
}
}
else if ( unlikely((x & PGT_count_mask) == 0) )
{
+ struct domain *d = page_get_owner(page);
+
+ /* Never allow a shadowed frame to go from type count 0 to 1 */
+ if ( d && shadow_mode_enabled(d) )
+ shadow_remove_all_shadows(d->vcpu[0], _mfn(page_to_mfn(page)));
+
ASSERT(!(x & PGT_pae_xen_l2));
if ( (x & PGT_type_mask) != type )
{
* may be unnecessary (e.g., page was GDT/LDT) but those
* circumstances should be very rare.
*/
- cpumask_t mask =
- page_get_owner(page)->domain_dirty_cpumask;
+ cpumask_t mask = d->domain_dirty_cpumask;
+
+ /* Don't flush if the timestamp is old enough */
tlbflush_filter(mask, page->tlbflush_timestamp);
if ( unlikely(!cpus_empty(mask)) &&
clear_bit(type >> PGC_SH_type_shift, &page->shadow_flags);
if ( (page->shadow_flags & SHF_page_type_mask) == 0 )
+ {
+ /* tlbflush timestamp field is valid again */
+ page->tlbflush_timestamp = tlbflush_current_time();
clear_bit(_PGC_page_table, &page->count_info);
+ }
}
/**************************************************************************/
extern void sh_remove_shadows(struct vcpu *v, mfn_t gmfn, int all);
static inline void shadow_remove_all_shadows(struct vcpu *v, mfn_t gmfn)
{
+ int was_locked = shadow_lock_is_acquired(v->domain);
+ if ( !was_locked )
+ shadow_lock(v->domain);
sh_remove_shadows(v, gmfn, 1);
+ if ( !was_locked )
+ shadow_unlock(v->domain);
}
/* Add a page to a domain */